#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"  	 
#include "Arduino.h"
#include "GUI.h"


static unsigned char _BitTableS[8]={0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
uint8_t OLED_GRAM[128][8];
//反显函数
void OLED_ColorTurn(uint8_t i)
{
	if(i==0)
		{
			OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
		}
	if(i==1)
		{
			OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
		}
}

//屏幕旋转180度
void OLED_DisplayTurn(uint8_t i)
{
	if(i==0)
		{
			OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
			OLED_WR_Byte(0xA1,OLED_CMD);
		}
	if(i==1)
		{
			OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
			OLED_WR_Byte(0xA0,OLED_CMD);
		}
}


//起始信号
void I2C_Start(void)
{
	OLED_SDIN_Set();
	OLED_SCLK_Set();
	ets_delay_us(1);
	OLED_SDIN_Clr();
	ets_delay_us(1);
	OLED_SCLK_Clr();
	ets_delay_us(1);
}

//结束信号
void I2C_Stop(void)
{
	ets_delay_us(1);
	OLED_SCLK_Set();
	ets_delay_us(1);
	OLED_SDIN_Clr();
	ets_delay_us(1);
	OLED_SDIN_Set();
	ets_delay_us(1);
}

//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
	OLED_SCLK_Set();
	ets_delay_us(1);
	OLED_SCLK_Clr();
	ets_delay_us(1);
}



//写入一个字节
void Send_Byte(uint8_t dat)
{
	uint8_t i;
	for(i=0;i<8;i++)
	{
		OLED_SCLK_Clr();//将时钟信号设置为低电平
		if(dat&0x80)//将dat的8位从最高位依次写入
		{
			OLED_SDIN_Set();
    }
		else
		{
			OLED_SDIN_Clr();
    }
		ets_delay_us(1);
		OLED_SCLK_Set();//将时钟信号设置为高电平
		ets_delay_us(1);
		OLED_SCLK_Clr();//将时钟信号设置为低电平
		ets_delay_us(1);
		dat<<=1;
  }
}

//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat,uint8_t mode)
{
	I2C_Start();
	Send_Byte(0x78);
	I2C_WaitAck();
	if(mode){Send_Byte(0x40);}
  else{Send_Byte(0x80);}
	I2C_WaitAck();
	Send_Byte(dat);
	I2C_WaitAck();
	I2C_Stop();
}

void OLED_WR_Byte_Keep(uint8_t dat,uint8_t mode)
{
	Send_Byte(dat);
	I2C_WaitAck();
}


//更新显存到OLED	
void OLED_Refresh(void)
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{
		OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
		OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
		OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
		I2C_Start();
		Send_Byte(0x78);
		I2C_WaitAck();
		Send_Byte(0x40);
		I2C_WaitAck();
		for(n=0;n<128;n++)
			OLED_WR_Byte_Keep(OLED_GRAM[n][i],OLED_DATA);
		I2C_Stop();
    }
	
}

//开启OLED显示 
void OLED_DisPlay_On(void)
{
	OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
	OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
	OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}

//关闭OLED显示 
void OLED_DisPlay_Off(void)
{
	OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
	OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
	OLED_WR_Byte(0xAF,OLED_CMD);//关闭屏幕
}


void OLED_RefreshPage(uint8_t page)
{
    uint8_t n=0;
    OLED_WR_Byte(0xb0+page,OLED_CMD); //设置行起始地址
    OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
    OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
    I2C_Start();
	Send_Byte(0x78);
	I2C_WaitAck();
	Send_Byte(0x40);
	I2C_WaitAck();
	for(n=0;n<128;n++)
		OLED_WR_Byte_Keep(OLED_GRAM[n][page],OLED_DATA);
	I2C_Stop();
}

//清屏函数
void OLED_Clear(void)
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{
	   for(n=0;n<128;n++)
        {
            OLED_GRAM[n][i]=0;//清除所有数据
        }
    }
	// OLED_Refresh();//更新显示
}

void OLED_ClearPage(uint8_t page,uint8_t color)
{
	uint8_t n;
    for(n=0;n<128;n++)
    {
        OLED_GRAM[n][page]=color;//清除所有数据
    }
}





//画点 
//x:0~127
//y:0~63
void OLED_DrawPoint(uint8_t x,uint8_t y)
{
	uint8_t i,m,n;
	x+=x_offset;
	i=y/8;
	m=y%8;
	n=1<<m;
	OLED_GRAM[x][i]|=n;
}

//清除一个点
//x:0~127
//y:0~63
void OLED_ClearPoint(uint8_t x,uint8_t y)
{
	uint8_t i,m,n;
	x+=x_offset;
	i=y/8;
	m=y%8;
	n=1<<m;
	OLED_GRAM[x][i]=~OLED_GRAM[x][i];
	OLED_GRAM[x][i]|=n;
	OLED_GRAM[x][i]=~OLED_GRAM[x][i];
}


//画线
//x:0~128
//y:0~64
void OLED_DrawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2)
{
	uint8_t i,k,k1,k2,y0;
	if((x1<0)||(x2>128)||(y1<0)||(y2>64)||(x1>x2)||(y1>y2))return;
	if(x1==x2)    //画竖线
	{
			for(i=0;i<(y2-y1);i++)
			{
				OLED_DrawPoint(x1,y1+i);
			}
  }
	else if(y1==y2)   //画横线
	{
			for(i=0;i<(x2-x1);i++)
			{
				OLED_DrawPoint(x1+i,y1);
			}
  }
	else      //画斜线
	{
		k1=y2-y1;
		k2=x2-x1;
		k=k1*10/k2;
		for(i=0;i<(x2-x1);i++)
			{
			  OLED_DrawPoint(x1+i,y1+i*k/10);
			}
	}
}
//x,y:圆心坐标
//r:圆的半径
void OLED_DrawCircle(uint8_t x,uint8_t y,uint8_t r)
{
	int a, b,num;
    a = 0;
    b = r;
    while(2 * b * b >= r * r)      
    {
        OLED_DrawPoint(x + a, y - b);
        OLED_DrawPoint(x - a, y - b);
        OLED_DrawPoint(x - a, y + b);
        OLED_DrawPoint(x + a, y + b);
 
        OLED_DrawPoint(x + b, y + a);
        OLED_DrawPoint(x + b, y - a);
        OLED_DrawPoint(x - b, y - a);
        OLED_DrawPoint(x - b, y + a);
        
        a++;
        num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
        if(num > 0)
        {
            b--;
            a--;
        }
    }
}



//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size:选择字体 12/16/24
//取模方式 逐列式
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size1)
{
	uint16_t i,m,temp,size2,chr1;
	uint16_t y0=y;
	size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
	chr1=chr-' ';  //计算偏移后的值
	for(i=0;i<size2;i++)
	{
		if(size1==12)
        {temp=asc2_1206[chr1][i];} //调用1206字体
		else if(size1==16)
        {temp=asc2_1608[chr1][i];} //调用1608字体
		else if(size1==24)
        {temp=asc2_2412[chr1][i];} //调用2412字体
		else if(size1==32)
        {temp=asc2_3216[chr1][i];} //调用6432字体
		else if(size1==64)
        {temp=asc2_6432[chr1][i];} //调用6432字体
		else return;
		for(m=0;m<8;m++)           //写入数据
		{
			if(temp&0x80)OLED_DrawPoint(x,y);
			else OLED_ClearPoint(x,y);
			temp<<=1;
			y++;
			if((y-y0)==size1)
			{
				y=y0;
				x++;
				break;
			}
		}
  }
}


//显示字符串
//x,y:起点坐标  
//size1:字体大小 
//*chr:字符串起始地址 
void OLED_ShowString(uint8_t x,uint8_t y,char *chr,uint8_t size1)
{
	while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
	{
		OLED_ShowChar(x,y,*chr,size1);
		x+=size1/2;
		if(x>128)  //换行
		{
			x=0;
			y+=16;
    }
		chr++;
  }
}

//m^n
uint32_t OLED_Pow(uint8_t m,uint8_t n)
{
	uint32_t result=1;
	while(n--)
	{
	  result*=m;
	}
	return result;
}

////显示2个数字
////x,y :起点坐标	 
////len :数字的位数
////size:字体大小
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size1)
{
	uint8_t t,temp;
	for(t=0;t<len;t++)
	{
		temp=(num/OLED_Pow(10,len-t-1))%10;
			if(temp==0)
			{
				OLED_ShowChar(x+(size1/2)*t,y,'0',size1);
      }
			else 
			{
			  OLED_ShowChar(x+(size1/2)*t,y,temp+'0',size1);
			}
  }
}

// //显示汉字
// //x,y:起点坐标
// //num:汉字对应的序号
// //取模方式 列行式
// void OLED_ShowChinese(uint8_t x,uint8_t y,uint8_t num,uint8_t size1)
// {
// 	uint8_t i,m,n=0,temp,chr1;
// 	uint8_t x0=x,y0=y;
// 	uint8_t size3=size1/8;
// 	while(size3--)
// 	{
// 		chr1=num*size1/8+n;
// 		n++;
// 			for(i=0;i<size1;i++)
// 			{
// 				if(size1==16)
// 						{temp=Hzk1[chr1][i];}//调用16*16字体
// 				else if(size1==24)
// 						{temp=Hzk2[chr1][i];}//调用24*24字体
// 				else if(size1==32)       
// 						{temp=Hzk3[chr1][i];}//调用32*32字体
// 				else if(size1==64)
// 						{temp=Hzk4[chr1][i];}//调用64*64字体
// 				else return;
							
// 						for(m=0;m<8;m++)
// 							{
// 								if(temp&0x01)OLED_DrawPoint(x,y);
// 								else OLED_ClearPoint(x,y);
// 								temp>>=1;
// 								y++;
// 							}
// 							x++;
// 							if((x-x0)==size1)
// 							{x=x0;y0=y0+8;}
// 							y=y0;
// 			 }
// 	}
// }

// //num 显示汉字的个数
// //space 每一遍显示的间隔
// void OLED_ScrollDisplay(uint8_t num,uint8_t space)
// {
// 	uint8_t i,n,t=0,m=0,r;
// 	while(1)
// 	{
// 		if(m==0)
// 		{
// 	    OLED_ShowChinese(100,13,t,16); //写入一个汉字保存在OLED_GRAM[][]数组中
// 			t++;
// 		}
// 		if(t==num)
// 			{
// 				for(r=0;r<16*space;r++)      //显示间隔
// 				 {
// 					for(i=0;i<144;i++)
// 						{
// 							for(n=0;n<8;n++)
// 							{
// 								OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
// 							}
// 						}
//            OLED_Refresh();
// 				 }
//         t=0;
//       }
// 		m++;
// 		if(m==16){m=0;}
// 		for(i=0;i<144;i++)   //实现左移
// 		{
// 			for(n=0;n<8;n++)
// 			{
// 				OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
// 			}
// 		}
// 		OLED_Refresh();
// 	}
// }

//配置写入数据的起始位置
void OLED_WR_BP(uint8_t x,uint8_t y)
{
	OLED_WR_Byte(0xb0+y,OLED_CMD);//设置行起始地址
	OLED_WR_Byte((((x+x_offset)&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WR_Byte(((x+x_offset)&0x0f),OLED_CMD);
}

//x0,y0：起点坐标
//BMP[]：要写入的图片数组
void OLED_ShowPicture(uint8_t x,uint8_t y,uint8_t width,uint8_t length,const uint8_t *pic)
{
    //控制OLED缓存刷新图片
	uint8_t i,n;
    uint32_t j=0;

    length = length/8;
    y = y/8;
    x += x_offset;

    for(i=y;i<y+length;i++)
	{
        for(n=x;n<x+width;n++)
        {
            OLED_GRAM[n][i]=pic[j];
            j++;
        }
    }
}
//OLED的初始化
void OLED_Init(void)
{
    pinMode(4,OUTPUT);
    pinMode(15,OUTPUT);
	pinMode(16,OUTPUT);
	delay(200);
	OLED_RST_Set();

	delay(200);

	OLED_RST_Clr();
	delay(800);
	OLED_RST_Set();

	OLED_WR_Byte(DISPLAYOFF,OLED_CMD);
	OLED_WR_Byte(SETDISPLAYCLOCKDIV,OLED_CMD);
	OLED_WR_Byte(0xF0,OLED_CMD); // Increase speed of the display max ~96Hz
	OLED_WR_Byte(SETMULTIPLEX,OLED_CMD);
	OLED_WR_Byte(63,OLED_CMD);
	OLED_WR_Byte(SETDISPLAYOFFSET,OLED_CMD);
	OLED_WR_Byte(0x00,OLED_CMD);
	OLED_WR_Byte(SETSTARTLINE,OLED_CMD);
	OLED_WR_Byte(CHARGEPUMP,OLED_CMD);
	OLED_WR_Byte(0x14,OLED_CMD);
	OLED_WR_Byte(MEMORYMODE,OLED_CMD);
	OLED_WR_Byte(0x00,OLED_CMD);
	OLED_WR_Byte(SEGREMAP,OLED_CMD);
	OLED_WR_Byte(COMSCANINC,OLED_CMD);
	OLED_WR_Byte(SETCOMPINS,OLED_CMD);

	OLED_WR_Byte(0x12,OLED_CMD);


	OLED_WR_Byte(SETCONTRAST,OLED_CMD);

	OLED_WR_Byte(0xCF,OLED_CMD);

	OLED_WR_Byte(SETPRECHARGE,OLED_CMD);
	OLED_WR_Byte(0xF1,OLED_CMD);
	OLED_WR_Byte(SETVCOMDETECT,OLED_CMD); //0xDB, (additionally needed to lower the contrast)
	OLED_WR_Byte(0x40,OLED_CMD);	        //0x40 default, to lower the contrast, put 0
	OLED_WR_Byte(DISPLAYALLON_RESUME,OLED_CMD);
	OLED_WR_Byte(NORMALDISPLAY,OLED_CMD);
	OLED_WR_Byte(0x2e,OLED_CMD);            // stop scroll
	OLED_WR_Byte(DISPLAYON,OLED_CMD);

    delay(200);
	OLED_Clear();
	OLED_Refresh();
}


void OLED_Debug(char *str,uint8_t line)
{
    if(line == 0)
    {
        OLED_ClearPage(0,BLACK);
        OLED_ClearPage(1,BLACK);
        OLED_ShowString(0,0,str,16);
        OLED_RefreshPage(0);
        OLED_RefreshPage(1);
    }
    else if(line == 1)
    {
        OLED_ClearPage(2,BLACK);
        OLED_ClearPage(3,BLACK);
        OLED_ShowString(0,16,str,16);
        OLED_RefreshPage(2);
        OLED_RefreshPage(3);
    }
	else if(line == 2)
    {
        OLED_ClearPage(4,BLACK);
        OLED_ClearPage(5,BLACK);
        OLED_ShowString(0,32,str,16);
        OLED_RefreshPage(4);
        OLED_RefreshPage(5);
    }
	else if(line == 3)
    {
        OLED_ClearPage(6,BLACK);
        OLED_ClearPage(7,BLACK);
        OLED_ShowString(0,48,str,16);
        OLED_RefreshPage(6);
        OLED_RefreshPage(7);
    }
}

void WriteByteBuffer(int page,int x,unsigned  char byte)
{
	OLED_GRAM[x][page]=byte;//清除所有数据
}



void FillByte(int page,int x,unsigned  char byte)
{
    WriteByteBuffer(page,x,OLED_GRAM[x][page]|byte);
}

void FillRect(int x,int y,int width,int height)
{
	int i,j;
	int temp =(y+height-1)/8-y/8;
	if(x>SCREEN_COLUMN ||y>SCREEN_ROW)   
			return;
	for(i=x;i<x+width&&i<128;i++)
	{
		if( temp==0 )
		{
			//ScreenBuffer[y/8][i] |=_BitTableS[height-1]<<(y%8);
			FillByte(y/8,i,_BitTableS[height-1]<<(y%8));
		}
		else
		{
			//ScreenBuffer[y/8][i] |=_BitTableS[(8-y%8)-1]<<(y%8);
			FillByte(y/8,i,_BitTableS[(8-y%8)-1]<<(y%8));
			for(j=1;j<temp;j++)
			{
				//ScreenBuffer[y/8+j][i] |=0xff;
				FillByte(y/8+j,i,0xff);
			}
			//ScreenBuffer[y/8+temp][i] |=_BitTableS[(height-1+y)%8];
			FillByte(y/8+temp,i,_BitTableS[(height-1+y)%8]);
			
		}	
	}
}




